package utils

import (
	"encoding/json"
	"fmt"
	"strings"
)

// EitherOr 三元表达式
// condition 判断条件
// trueVal 条件成立返回值
// falseVal 条件不成立返回值
// 返回：返回符合条件的值
func EitherOr[T any](condition bool, trueVal, falseVal T) T {
	if condition {
		return trueVal
	}
	return falseVal
}

// IsNil 判断对象是否为空
// val 被判断对象
// 返回：true：为空，false：不为空
func IsNil[T any](val *T) bool {
	return EitherOr(val == nil, true, false)
}

// IsNotNil 判断对象不为空
// val 被判断对象
// 返回：true：不为空，false：为空
func IsNotNil[T any](val *T) bool {
	return EitherOr(val != nil, true, false)
}

// IsStrEmpty 判断字符串是否为空
// val 被判断的字符串
// 返回：true：为空，false：不为空
func IsStrEmpty[T ~string](val T) bool {
	return EitherOr(val == "", true, false)
}

// NewEmptySlice 创建一个空切片
// 返回：返回空的切片
func NewEmptySlice[T any]() []T {
	return make([]T, 0)
}

// PointerConvert 将指针转换成类型值
// val 指针
// 返回：返回对应指针类型值，若为空则返回该类型的默认值
func PointerConvert[T any](val *T) T {
	var v T
	return EitherOr(val != nil, *val, v)
}

// Desensitize 字符串脱敏
// val 脱敏值
// start 从第几位开始脱敏
// end 到第几位结束脱敏
// 返回：脱敏的数据
func Desensitize(val string, start, end int) string {
	if IsStrEmpty[string](val) {
		return val
	}
	if start < 0 || start > len(val) || end > len(val) || start > end {
		return val
	}
	return fmt.Sprintf("%s%s%s", val[0:start], strings.Repeat("*", end-start), val[end:])
}

// CopyProperties 拷贝属性为一个新的指针
// val 需要拷贝的参数
// 返回指针
func CopyProperties[T any](val T) *T {
	var res T
	bytes, err := json.Marshal(val)
	if err != nil {
		panic(err)
	}
	if err := json.Unmarshal(bytes, &res); err != nil {
		panic(err)
	}
	return &res
}

// CopyProperties1 根据传入源对象和目标对象进行拷贝
// source 源对象
// target 目标对象
// 返回：不返回错误说明拷贝成功，返回错误说明拷贝失败
func CopyProperties1[T any](source T, target *T) error {
	bytes, err := json.Marshal(source)
	if err != nil {
		return err
	}
	err = json.Unmarshal(bytes, target)
	return EitherOr(err != nil, err, nil)
}

// ObjectToJsonStr 将对象转成字符串
// obj 对象
// 返回 转成json字符串
func ObjectToJsonStr(obj interface{}) string {
	if obj == nil {
		return ""
	}
	data, err := json.Marshal(obj)
	return EitherOr[string](err != nil, "", string(data))
}
